/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.task.support.scripting;

import cn.easyplatform.EasyPlatformWithLabelKeyException;
import cn.easyplatform.lang.Files;
import cn.easyplatform.lang.Nums;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.messages.request.ExpressionRequestMessage;
import cn.easyplatform.messages.request.SimpleTextRequestMessage;
import cn.easyplatform.messages.vos.ExpressionVo;
import cn.easyplatform.messages.vos.datalist.ListExpressionVo;
import cn.easyplatform.messages.vos.datalist.ListHeaderVo;
import cn.easyplatform.spi.service.ApplicationService;
import cn.easyplatform.type.FieldType;
import cn.easyplatform.type.IResponseMessage;
import cn.easyplatform.type.ListRowVo;
import cn.easyplatform.web.WebApps;
import cn.easyplatform.web.contexts.Contexts;
import cn.easyplatform.web.ext.ZkExt;
import cn.easyplatform.web.service.ServiceLocator;
import cn.easyplatform.web.task.BackendException;
import cn.easyplatform.web.task.EventSupport;
import cn.easyplatform.web.task.MainTaskSupport;
import cn.easyplatform.web.task.OperableHandler;
import cn.easyplatform.web.task.zkex.ComponentBuilderFactory;
import cn.easyplatform.web.task.zkex.ListSupport;
import cn.easyplatform.web.task.zkex.list.PanelSupport;
import cn.easyplatform.web.utils.ExtUtils;
import cn.easyplatform.web.utils.PageUtils;
import cn.easyplatform.web.utils.WebUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zkoss.util.Locales;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Components;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.*;
import org.zkoss.zul.impl.FormatInputElement;
import org.zkoss.zul.impl.HeaderElement;
import org.zkoss.zul.impl.XulElement;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.*;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class UtilsCmd {

    protected final static Logger log = LoggerFactory.getLogger(UtilsCmd.class);

    public static final int C_ONE_SECOND = 1000;

    public static final int C_ONE_MINUTE = 60 * C_ONE_SECOND;

    public static final long C_ONE_HOUR = 60 * C_ONE_MINUTE;

    public static final long C_ONE_DAY = 24 * C_ONE_HOUR;

    private Map<String, Object> cache;

    protected EventSupport handler;

    protected Component anchor;

    protected Map<String, Object> scope;

    protected String breakMethod;

    public UtilsCmd(EventSupport handler, Map<String, Object> scope) {
        this.handler = handler;
        this.scope = scope;
    }

    public void setAnchor(Component anchor) {
        this.anchor = anchor;
    }

    public void debug(Object msg) {
        if (log.isDebugEnabled())
            log.debug("UtilsCmd->{}，{}", handler == null ? "" : handler.getId(),
                    msg);
    }

    public void log(Object msg) {
        Clients.log(msg);
    }

    public void alert(Object msg) {
        Clients.alert(msg == null ? "" : msg.toString());
    }

    public void sendRedirect(String url, String target) {
        if (Strings.isBlank(target)) {
            Clients.confirmClose("");
            Executions.sendRedirect(url);
        } else
            Executions.getCurrent().sendRedirect(url, target);
    }

    public String getContextPath() {
        return WebApps.getContextPath();
    }

    public String i18n(String name) {
        ApplicationService ac = ServiceLocator
                .lookup(ApplicationService.class);
        IResponseMessage<?> resp = ac.i18n(new SimpleTextRequestMessage(name));
        if (resp.isSuccess())
            return (String) resp.getBody();
        throw new BackendException(resp);
    }

    public boolean isEmpty(Object value) {
        if (value == null)
            return true;
        if (value.toString().trim().equals(""))
            return true;
        return false;
    }

    public boolean isEquals(Object src, Object target) {
        if (src == null && target == null)
            return true;
        if (src == null || target == null)
            return false;
        if (src.equals(target))
            return true;
        if (!src.getClass().isAssignableFrom(target.getClass())
                && !target.getClass().isAssignableFrom(src.getClass()))
            return false;
        if (src instanceof Date) {
            Calendar cal1 = Calendar.getInstance();
            cal1.setTime((Date) src);
            Calendar cal2 = Calendar.getInstance();
            cal2.setTime((Date) target);
            if (cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR)
                    && cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH)
                    && cal1.get(Calendar.DATE) == cal2.get(Calendar.DATE))
                return true;
        }
        return false;
    }

    public int toInt(Object o) {
        return Nums.toInt(o, 0);
    }

    public long toLong(Object o) {
        return Nums.toLong(o, 0);
    }

    public double toDouble(Object o) {
        if (o == null)
            return 0d;
        if (o instanceof Number)
            return ((Number) o).doubleValue();
        try {
            return Double.parseDouble(o.toString());
        } catch (NumberFormatException ex) {
            return 0d;
        }
    }

    public String toStr(Object value, String tp) {
        if (value == null)
            return "";
        if (Strings.isBlank(tp))
            tp = "INT";
        FieldType type = FieldType.valueOf(tp.toUpperCase());
        switch (type) {
            case CHAR:
            case VARCHAR:
            case CLOB:
            case BOOLEAN:
            case DATETIME:
            case TIME:
            case DATE:
                return value.toString();
            case INT:
                if (value instanceof Number)
                    return ((Number) value).intValue() + "";
                else
                    return "" + Nums.toInt(value, 0);
            case LONG:
                if (value instanceof Number)
                    return ((Number) value).longValue() + "";
                else
                    return "" + Nums.toLong(value, 0);
            case NUMERIC:
                if (value instanceof Number)
                    return ((Number) value).doubleValue() + "";
                else
                    return value.toString();
            default:
                throw new EasyPlatformWithLabelKeyException("dao.access.getType",
                        "", type);
        }
    }

    public String format(Object o, String pattern) {
        if (o == null)
            return "";
        if (o instanceof Date) {
            if (!Strings.isBlank(pattern))
                return DateFormatUtils.format((Date) o, pattern);
            else
                return DateFormat.getDateInstance(DateFormat.MEDIUM,
                        Locales.getCurrent()).format((Date) o);
        } else if (o instanceof Number) {
            if (!Strings.isBlank(pattern)) {
                DecimalFormat dm = new DecimalFormat(pattern);
                return dm.format(o);
            } else
                return DecimalFormat.getInstance(Locales.getCurrent())
                        .format(o);

        } else
            return o.toString();
    }

    public Date toDate(String str, String pattern) {
        if (Strings.isBlank(str))
            return null;
        if (Strings.isBlank(pattern))
            pattern = "yyyyMMdd";
        SimpleDateFormat format = new SimpleDateFormat(pattern);
        try {
            return format.parse(str);
        } catch (ParseException e) {
            return null;
        }
    }

    public Date toDay(Date datetime) {
        if (datetime == null)
            return datetime = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        String day = format.format(datetime);
        try {
            return format.parse(day);
        } catch (ParseException e) {
        }
        return null;
    }

    public int getHours(Date firstDate, Date secondDate) {
        Calendar firstCalendar = Calendar.getInstance(Locales.getCurrent());
        firstCalendar.setTime(firstDate);
        Calendar secondCalendar = Calendar.getInstance(Locales.getCurrent());
        secondCalendar.setTime(secondDate);
        if (firstCalendar.after(secondCalendar)) {
            Calendar calendar = firstCalendar;
            firstCalendar = secondCalendar;
            secondCalendar = calendar;
        }
        long calendarNum1 = firstCalendar.getTimeInMillis();
        long calendarNum2 = secondCalendar.getTimeInMillis();
        return Math.abs((int) ((calendarNum1 - calendarNum2) / C_ONE_HOUR));
    }

    public int getDays(Date firstDate, Date secondDate) {
        Calendar firstCalendar = Calendar.getInstance(Locales.getCurrent());
        firstCalendar.setTime(firstDate);
        Calendar secondCalendar = Calendar.getInstance(Locales.getCurrent());
        secondCalendar.setTime(secondDate);
        if (firstCalendar.after(secondCalendar)) {
            Calendar calendar = firstCalendar;
            firstCalendar = secondCalendar;
            secondCalendar = calendar;
        }
        long calendarNum1 = firstCalendar.getTimeInMillis();
        long calendarNum2 = secondCalendar.getTimeInMillis();
        return Math.abs((int) ((calendarNum1 - calendarNum2) / C_ONE_DAY));
    }

    public int getMonths(Date firstDate, Date secondDate) {
        Calendar firstCalendar = Calendar.getInstance(Locales.getCurrent());
        firstCalendar.setTime(firstDate);
        Calendar secondCalendar = Calendar.getInstance(Locales.getCurrent());
        secondCalendar.setTime(secondDate);
        if (firstCalendar.after(secondCalendar)) {
            Calendar calendar = firstCalendar;
            firstCalendar = secondCalendar;
            secondCalendar = calendar;
        }
        int flag = 0;
        if (secondCalendar.get(Calendar.DAY_OF_MONTH) < firstCalendar
                .get(Calendar.DAY_OF_MONTH))
            flag = 1;
        if (secondCalendar.get(Calendar.YEAR) > firstCalendar
                .get(Calendar.YEAR))
            return ((secondCalendar.get(Calendar.YEAR) - firstCalendar
                    .get(Calendar.YEAR))
                    * 12
                    + secondCalendar.get(Calendar.MONTH) - flag)
                    - firstCalendar.get(Calendar.MONTH);
        else
            return secondCalendar.get(Calendar.MONTH)
                    - firstCalendar.get(Calendar.MONTH) - flag;
    }

    public Date addDays(Date date, int day) {
        if (date == null)
            date = new Date();
        Calendar calendar = Calendar.getInstance(Locales.getCurrent());
        calendar.setTime(date);
        calendar.add(Calendar.DATE, day);
        return calendar.getTime();
    }

    public Date addMonths(Date date, int months) {
        if (date == null)
            date = new Date();
        Calendar calendar = Calendar.getInstance(Locales.getCurrent());
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, months);
        return calendar.getTime();
    }

    public Date addYears(Date date, int years) {
        if (date == null)
            date = new Date();
        Calendar calendar = Calendar.getInstance(Locales.getCurrent());
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, years);
        return calendar.getTime();
    }

    public int getMaxDayInMonth(int year, int month) {
        Calendar calendar = Calendar.getInstance(Locales.getCurrent());
        if (year == 0 || month == 0) {
            Date date = new Date();
            Calendar c = Calendar.getInstance(Locales.getCurrent());
            c.setTime(date);
            if (year == 0)
                year = c.get(Calendar.YEAR);
            if (month == 0)
                month = c.get(Calendar.MONTH - 1);
        }
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    public int getRemainingDays(Date date) {
        if (date == null)
            date = new Date();
        Calendar calendar = Calendar.getInstance(Locales.getCurrent());
        calendar.setTime(date);
        int maxDate = calendar.getActualMaximum(Calendar.DATE);
        return maxDate = maxDate - calendar.get(Calendar.DATE);
    }

    public int getDayOfYear(Date date) {
        if (date == null)
            date = new Date();
        Calendar calendar = Calendar.getInstance(Locales.getCurrent());
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_YEAR);
    }

    public int getDayOfWeek(Date date) {
        if (date == null)
            date = new Date();
        Calendar calendar = Calendar.getInstance(Locales.getCurrent());
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_WEEK);
    }

    public int getWeekOfYear(Date date) {
        if (date == null)
            date = new Date();
        Calendar calendar = Calendar.getInstance(Locales.getCurrent());
        calendar.setTime(date);
        return calendar.get(Calendar.WEEK_OF_YEAR);
    }

    public int getWeekOfMonth(Date date) {
        if (date == null)
            date = new Date();
        Calendar calendar = Calendar.getInstance(Locales.getCurrent());
        calendar.setTime(date);
        return calendar.get(Calendar.WEEK_OF_MONTH);
    }

    public int getMaxDayInMonth(Date date) {
        Calendar c = Calendar.getInstance(Locales.getCurrent());
        c.setTime(date);
        return c.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    public Date now() {
        return new Date();
    }

    public Object cache(String name, Object value) {
        if (cache == null)
            cache = new HashMap<String, Object>();
        if (value != null)
            return cache.put(name, value);
        else
            return cache.get(name);
    }

    /**
     * 替换控件
     *
     * @param oldc
     * @param newc
     */
    public Component replace(Component oldc, Object newc, Object value) {
        if (oldc == null)
            throw new IllegalArgumentException("replace:oldc is not null.");
        if (newc == null)
            throw new IllegalArgumentException("replace:newc is not null.");
        if (newc instanceof Component) {
            if (oldc instanceof Listcell || oldc instanceof Treecell)
                oldc.appendChild((Component) newc);
            else
                Components.replace(oldc, (Component) newc);
            if (value != null)
                PageUtils.setValue((Component) newc, value);
            return (Component) newc;
        } else if (newc instanceof CharSequence) {
            String zul = ((CharSequence) newc).toString();
            XulElement comp = (XulElement) Executions.createComponentsDirectly(
                    zul, "zul", null, null);
            if (comp instanceof ZkExt) {
                if (handler instanceof ListSupport) {
                    ComponentBuilderFactory.getZkBuilder((ListSupport) handler,
                            (ZkExt) comp, anchor).build();
                } else
                    ComponentBuilderFactory.getZkBuilder(
                            (OperableHandler) handler, (ZkExt) comp);
            }
            if (oldc instanceof Listcell || oldc instanceof Treecell)
                oldc.appendChild(comp);
            else
                Components.replace(oldc, comp);
            if (value != null)
                PageUtils.setValue(comp, value);
            return comp;
        }
        return null;
    }

    /**
     * 执行查询、更新、表达式
     *
     * @param expr
     * @param type
     * @param args
     * @return
     */
    public Object evalExpression(String expr, int type, Component... args) {
        return evalExpression(expr, type, 0, args);
    }

    /**
     * 执行查询、更新、表达式
     *
     * @param expr
     * @param type
     * @param actionFlag
     * @param args
     * @return
     */
    public Object evalExpression(String expr, int type, int actionFlag, Component... args) {
        ExpressionVo lv = null;
        Map<String, Object> values = new HashMap<String, Object>();
        for (Component c : args)
            values.put(c.getId(), PageUtils.getValue(c, false));
        if (handler instanceof ListSupport || handler instanceof PanelSupport) {
            ListSupport dls = null;
            Object[] data = null;
            if (handler instanceof ListSupport) {
                dls = (ListSupport) handler;
                Object self = scope.get("self");
                ListRowVo rv = null;
                if (self != null) {
                    if (self instanceof Listitem)
                        rv = ((Listitem) self).getValue();
                    else if (self instanceof Treeitem)
                        rv = ((Treeitem) self).getValue();
                    else if (self instanceof Row)
                        rv = ((Row) self).getValue();
                    else
                        rv = dls.getSelectedValue();
                } else
                    rv = dls.getSelectedValue();
                if (rv != null)
                    data = dls.isCustom() ? rv.getData() : rv.getKeys();
            } else
                dls = ((PanelSupport) handler).getList();
            lv = new ListExpressionVo(type, expr, values, dls.getComponent()
                    .getId(), data);
        } else
            lv = new ExpressionVo(type, expr, values);
        ExpressionRequestMessage req = new ExpressionRequestMessage(
                handler.getId(), lv);
        if (actionFlag != 0)
            req.setActionFlag(actionFlag);
        IResponseMessage<?> resp = ServiceLocator.lookup(
                ApplicationService.class).executeExpression(req);
        if (!resp.isSuccess()) {
            char c = resp.getCode().toLowerCase().charAt(0);
            if (c == 'c' || c == 'w')
                breakMethod = "eval";
            throw new BackendException(resp);
        }
        return resp.getBody();
    }

    /**
     * 设置acc
     *
     * @param comp
     * @param acc
     */
    public void setAcc(Component comp, Object acc) {
        if (comp instanceof FormatInputElement) {
            if (acc instanceof Component)
                acc = PageUtils.getValue((Component) acc, false);
            if (acc instanceof Number)
                ((FormatInputElement) comp).setFormat(WebUtils
                        .getFormat(((Number) acc).intValue()));
            else if (acc instanceof String)
                ((FormatInputElement) comp).setFormat(WebUtils.getFormat(
                        handler.getId(), (String) acc));
        }
    }

    /**
     * 获取表头名称
     *
     * @param index
     * @return
     */
    public String getColumnName(int index) {
        HeaderElement header = getHeader(index);
        if (header != null)
            return header.getLabel();
        return "";
    }

    /**
     * 获取表头名称
     *
     * @param name
     */
    public String getColumnName(String name) {
        HeaderElement header = getHeader(name);
        if (header != null)
            return header.getLabel();
        return "";
    }

    /**
     * 改变列的名称
     *
     * @param index
     * @param title
     * @return
     */
    public Component setColumnName(int index, String title) {
        HeaderElement header = getHeader(index);
        if (header != null)
            header.setLabel(title);
        return header;
    }

    /**
     * 改变列的名称
     *
     * @param name
     * @param title
     */
    public Component setColumnName(String name, String title) {
        HeaderElement header = getHeader(name);
        if (header != null)
            header.setLabel(title);
        return header;
    }

    /**
     * @param index
     * @param visible
     * @return
     */
    public Component setColumnVisible(int index, boolean visible) {
        HeaderElement header = getHeader(index);
        if (header != null) {
            header.setVisible(visible);
            if (header instanceof Column) {
                ListHeaderVo hv = ((Column) header).getValue();
                if (hv != null)
                    hv.setVisible(visible);
            } else if (header instanceof Listheader) {
                ListHeaderVo hv = ((Listheader) header).getValue();
                if (hv != null)
                    hv.setVisible(visible);
            } else {
                ListHeaderVo hv = (ListHeaderVo) header.getAttribute("value");
                if (hv != null)
                    hv.setVisible(visible);
            }
        }
        return header;
    }

    /**
     * 使某列可否显示
     *
     * @param name
     * @param visible
     */
    public Component setColumnVisible(String name, boolean visible) {
        String[] names = name.split(",");
        HeaderElement header = null;
        for (String n : names) {
            header = getHeader(n);
            if (header != null) {
                if (header.getLabel().startsWith("$")) {
                    Object val = WebUtils.getFieldValue(handler, header.getLabel().substring(1));
                    if (val != null)
                        header.setLabel(val.toString());
                }
                header.setVisible(visible);
                if (header instanceof Column) {
                    ListHeaderVo hv = ((Column) header).getValue();
                    hv.setVisible(visible);
                } else if (header instanceof Listheader) {
                    ListHeaderVo hv = ((Listheader) header).getValue();
                    hv.setVisible(visible);
                } else {
                    ListHeaderVo hv = (ListHeaderVo) header.getAttribute("value");
                    hv.setVisible(visible);
                }
            }
        }
        return header;
    }

    public int getColumnSize() {
        ListSupport op = null;
        if (handler instanceof ListSupport) {
            op = (ListSupport) handler;
        } else if (handler instanceof PanelSupport) {
            op = ((PanelSupport) handler).getList();
        }
        if (op != null) {
            if (op.getComponent() instanceof Listbox) {
                return ((Listbox) op.getComponent())
                        .getListhead().getChildren().size();
            }
            if (op.getComponent() instanceof Grid) {
                return ((Grid) op.getComponent()).getColumns().getChildren().size();
            } else {
                return ((Tree) op.getComponent())
                        .getTreecols().getChildren().size();
            }
        }
        return -1;
    }

    public String[] getColumns() {
        ListSupport op = null;
        if (handler instanceof ListSupport) {
            op = (ListSupport) handler;
        } else if (handler instanceof PanelSupport) {
            op = ((PanelSupport) handler).getList();
        }
        List<String> columns = new ArrayList<String>();
        if (op != null) {
            if (op.getComponent() instanceof Listbox) {
                List<Listheader> headers = ((Listbox) op.getComponent())
                        .getListhead().getChildren();
                for (Listheader header : headers) {
                    ListHeaderVo hv = header.getValue();
                    if (hv != null)
                        columns.add(hv.getTitle());
                }
            } else if (op.getComponent() instanceof Grid) {
                List<Column> headers = ((Grid) op.getComponent())
                        .getColumns().getChildren();
                for (Column header : headers) {
                    ListHeaderVo hv = header.getValue();
                    if (hv != null)
                        columns.add(hv.getTitle());
                }
            } else {
                List<Treecol> headers = ((Tree) op.getComponent())
                        .getTreecols().getChildren();
                for (Treecol header : headers) {
                    ListHeaderVo hv = (ListHeaderVo) header
                            .getAttribute("value");
                    if (hv != null)
                        columns.add(hv.getTitle());
                }
            }
        }
        String[] result = new String[columns.size()];
        columns.toArray(result);
        return result;
    }

    /**
     * @param name
     * @return
     */
    public HeaderElement getHeader(String name) {
        ListSupport op = null;
        if (handler instanceof ListSupport) {
            op = (ListSupport) handler;
        } else if (handler instanceof PanelSupport) {
            op = ((PanelSupport) handler).getList();
        }
        if (op != null) {
            if (op.getComponent() instanceof Listbox) {
                List<Listheader> headers = ((Listbox) op.getComponent())
                        .getListhead().getChildren();
                for (Listheader header : headers) {
                    ListHeaderVo hv = header.getValue();
                    if (hv != null && hv.getName().equals(name))
                        return header;
                }
            } else if (op.getComponent() instanceof Grid) {
                List<Column> headers = ((Grid) op.getComponent())
                        .getColumns().getChildren();
                for (Column header : headers) {
                    ListHeaderVo hv = header.getValue();
                    if (hv != null && hv.getName().equals(name))
                        return header;
                }
            } else {
                List<Treecol> headers = ((Tree) op.getComponent())
                        .getTreecols().getChildren();
                for (Treecol header : headers) {
                    ListHeaderVo hv = (ListHeaderVo) header
                            .getAttribute("value");
                    if (hv != null && hv.getName().equals(name))
                        return header;
                }
            }
        }
        return null;
    }

    /**
     * @param index
     * @return
     */
    public HeaderElement getHeader(int index) {
        ListSupport op = null;
        if (handler instanceof ListSupport) {
            op = (ListSupport) handler;
        } else if (handler instanceof PanelSupport) {
            op = ((PanelSupport) handler).getList();
        }
        if (op != null) {
            if (op.getComponent() instanceof Listbox) {
                return (HeaderElement) ((Listbox) op.getComponent())
                        .getListhead().getChildren().get(index);
            } else if (op.getComponent() instanceof Grid) {
                return (HeaderElement) ((Grid) op.getComponent()).getColumns().getChildren().get(index);
            } else {
                return (HeaderElement) ((Tree) op.getComponent()).getTreecols()
                        .getChildren().get(index);
            }
        }
        return null;
    }

    /**
     * 保存到文件
     *
     * @param fn
     * @param data
     * @return
     */
    public String toFile(String fn, Object data) {
        if (fn.contains("&dt"))
            fn = fn.replace("&dt", DateFormatUtils.format(new Date(), "yyyyMMdd"));
        Files.write(WebUtils.getFile(fn), data);
        return fn;
    }

    /**
     * 读文件
     *
     * @param fn
     * @return
     */
    public Object fromFile(String fn) {
        return WebUtils.getFileContent(fn);
    }

    /**
     * 转Json格式到对象
     *
     * @param json
     * @return
     */
    public Object fromJson(String json) {
        return ExtUtils.fromJson(json);
    }

    /**
     * 转对象为json格式
     *
     * @param obj
     * @return
     */
    public String toJson(Object obj) {
        return ExtUtils.toJson(obj);
    }

    /**
     * 在当前功能设置有效的变量
     *
     * @param name
     * @param value
     */
    public void set(String name, Object value) {
        getMainTask().set(name, value);
    }

    /**
     * 根据名称获取变量值
     *
     * @param name
     * @return
     */
    public Object get(String name) {
        return getMainTask().get(name);
    }

    /**
     * 移除指定的变量
     *
     * @param name
     * @return
     */
    public Object remove(String name) {
        return getMainTask().remove(name);
    }

    /**
     * 获取主功能
     *
     * @return
     */
    protected MainTaskSupport getMainTask() {
        MainTaskSupport support = null;
        if (handler instanceof MainTaskSupport)
            support = (MainTaskSupport) handler;
        else if (handler instanceof ListSupport)
            support = (MainTaskSupport) ((ListSupport) handler).getMainHandler();
        else if (handler instanceof PanelSupport)
            support = (MainTaskSupport) ((PanelSupport) handler).getList().getMainHandler();
        return support;
    }

    public void setValue(Object target, Object value, String... type) {
        if (target instanceof String) {
            WebUtils.setFieldValue(handler, (String) target, value);
        } else if (target instanceof Component)
            PageUtils.setValue((Component) target, value);

    }

    public Object getValue(Object target, String... type) {
        if (target instanceof String) {
            return WebUtils.getFieldValue(handler, (String) target);
        } else
            return PageUtils.getValue((Component) target, false);
    }

    /**
     * 动态获取上下文中的变量对象
     *
     * @param name
     * @return
     */
    public Object getObject(String name) {
        if (scope.containsKey(name))
            return scope.get(name);
        else if (name.startsWith("$")) {
            name = name.substring(1);
            return WebUtils.getFieldValue(handler, name);
        }
        return null;
    }

    public String getWorkspace() {
        return FilenameUtils.normalize(WebApps.me().getWorkspace() + "/" + Contexts.getEnv().getProjectId());
    }

}
